package cn.edu.suda.ada.database.parser;

import cn.edu.suda.ada.common.config.Config;
import cn.edu.suda.ada.database.connection.DbProperties;
import cn.edu.suda.ada.database.exception.DatabaseException;
import cn.edu.suda.ada.database.objects.Column;
import cn.edu.suda.ada.database.objects.Key;
import cn.edu.suda.ada.database.objects.Table;

import java.util.Map;

/**
 * SQL解析类
 * 
 * @author JiangJun
 * 
 */
public abstract class DbParser {
	/**
	 * 当前增删改查的SQL
	 */
	protected String sql;
	
	/**
	 * 字符串查询条件
	 */
	public static String WHERE_STRING = "_string";

	/**
	 * 偏移量关键字
	 */
	public static String OFFSET_KEYWORD = "OFFSET";

	/**
	 * 查询语句模板
	 */
	public enum SQLTemplate {
		SELECT_SQL("SELECT %DISTINCT% %FIELD% FROM %TABLE% %JOIN% %WHERE% %GROUP% %HAVING% %ORDER% %LIMIT% %UNION%"),
		DELETE_SQL("DELETE FROM %TABLE% %WHERE%"),
		UPDATE_SQL("UPDATE %TABLE% SET %DATA% %WHERE%"),
		INSERT_SQL("INSERT INTO %TABLE%(%FIELD%) VALUES(%DATA%)");
		private String template;
		SQLTemplate(String template){
			this.template = template;
		}
		@Override
		public String toString() {
			return template;
		}
	}

	/**
	 * 增删该查需要用到的一些参数
	 */
	public enum OPTIONS {
		DISTINCT,FIELD,TABLE,JOIN,WHERE,GROUP,HAVING,ORDER,LIMIT,UNION,DATA;
	}

	/**
	 * 获取具体的SQL解析实例
	 *
	 * @param path 配置文件地址
	 * @return SQL解析实例
	 * @throws DatabaseException 无法加载解析类
	 */
	public static DbParser getInstance(String path) throws DatabaseException {
		Config config = DbProperties.getConfig(path);
		try {
			String type = config.getString("jdbc.type");
			if (null == type) {
				type = "mysql";
			}
			type = type.toUpperCase();
			if (type.equals("MYSQL") || type.equals("MYSQLI")) {
				type = "Mysql";
			}
			else if (type.equals("SQLSERVER") || type.equals("MSSQL") || type.equals("SQL SERVER")) {
				type = "Mssql";
			}
			else {
				throw new DatabaseException("不支持该数据库类型！");
			}
			return (DbParser) Class.forName("cn.edu.suda.ada.database.parser." + type + "DbParser").newInstance();
		} catch (InstantiationException e) {
			throw new DatabaseException("无法实例化数据库解析类！", e);
		} catch (IllegalAccessException e) {
			throw new DatabaseException("无权实例化数据库解析类！", e);
		} catch (ClassNotFoundException e) {
			throw new DatabaseException("未找到数据库解析类！", e);
		}
	}

	/**
	 * 解析SQL模版
	 *
	 * @param sqlTemplate 解析模板类型
	 * @param options 参数
	 * @return SQL语句
	 */
	protected abstract String parserSql(SQLTemplate sqlTemplate, Map<OPTIONS, Object> options);
	
	// 数据表操作相关
	/**
	 * 创建表SQL
	 * 
	 * @param table 数据表信息
	 * @return SQL语句
	 */
	public abstract String createTable(Table table);

	/**
	 * 创建列SQL
	 * 
	 * @param column 数据列实例
	 * @return SQL语句
	 */
	public abstract String createColumn(Column<?> column);

	/**
	 * 创建索引SQL
	 * 
	 * @param key 索引信息
	 * @return SQL语句
	 */
	public abstract String createKey(Key key);

	/**
	 * 删除表SQL
	 * 
	 * @param tableName 表名
	 * @return SQL语句
	 */
	public abstract String dropTable(String tableName);

	/**
	 * 检查表是否存在，等效于设置 <code>options (TABLE/WHERE)</code> 参数
	 * 
	 * @param tableName 表名
	 * @return SQL语句
	 */
	public abstract String exist(String tableName);
	
	// 获得表结构
	/**
	 * 显示某张表信息SQL
	 * 
	 * @param tableName 表名
	 * @param databaseName 数据库名
	 * @return SQL语句
	 */
	public abstract String showTable(String tableName, String databaseName);
	
	/**
	 * 将  <code>showTable()</code> 执行后获取到的表信息 <code>Map</code> 转化为 <code>Table</code> 对象
	 * 
	 * @param map 表信息
	 * @return 数据表实例
	 */
	public abstract Table mapToTable(Map<String, Object> map);
	
	/**
	 * 获得所有数据列SQL
	 * 
	 * @param tableName 表名
	 * @return SQL语句
	 */
	public abstract String showColumns(String tableName);
	
	/**
	 * 将  <code>showColumns()</code> 执行后获取到的列信息 <code>Map</code> 转化为 <code>Table</code> 对象
	 * 
	 * @param map 列信息
	 * @return 数据列实例
	 */
	public abstract Column<?> mapToColumn(Map<String, Object> map);
	/**
	 * 获得所有索引结构信息SQL
	 * 
	 * @param tableName 表名
	 * @return SQL语句
	 */
	public abstract String showKeys(String tableName);
	/**
	 * 将 <code>showKeys()</code> 执行后获取到的索引信息 <code>Map</code> 转化为 <code>Key</code> 对象
	 * 
	 * @param map 索引信息
	 * @return 索引实例
	 */
	public abstract Key mapToKey(Map<String, Object> map);
	
	/**
	 * 修改列SQL
	 * 
	 * @param tableName 表名
	 * @param oldColumn 原来的列信息
	 * @param newColumn 新的列信息
	 * @return SQL语句
	 */
	public abstract String alterColumn(String tableName, Column<?> oldColumn, Column<?> newColumn);

	/**
	 * 删除列SQL
	 * 
	 * @param tableName 表名
	 * @param columnName 删除列的名称
	 * @return SQL语句
	 */
	public abstract String dropColumn(String tableName, String columnName);
	
	/**
	 * 新增列SQL
	 * 
	 * @param tableName 表名
	 * @param column 新增列信息
	 * @return SQL语句
	 */
	public abstract String addColumn(String tableName,Column<?> column);
	
	/**
	 * 复制表及数据SQL
	 * 
	 * @param tableName 原始表名
	 * @param newTableName 新表名称
	 * @return SQL语句
	 */
	public abstract String copyTableStructure(String tableName, String newTableName);
	/**
	 * 复制表及数据SQL
	 * 
	 * @param tableName 原始表名
	 * @param newTableName 新表名称
	 * @return SQL语句
	 */
	public abstract String copyTable(String tableName, String newTableName);
	
	// 数据查询相关
	/**
	 * 获得查询SQL
	 * 
	 * @param options 参数
	 * @return SQL语句
	 */
	public abstract String select(Map<OPTIONS, Object> options);

	/**
	 * 统计行数SQL
	 * 
	 * @param options 参数
	 * @param field 字段
	 * @return SQL语句
	 */
	public abstract String count(Map<OPTIONS, Object> options, String field);

	/**
	 * 删除SQL
	 * 
	 * @param options 参数
	 * @return SQL语句
	 */
	public abstract String delete(Map<OPTIONS, Object> options);
	
	/**
	 * 新增SQL
	 *  
	 * @param options 参数
	 * @return SQL语句
	 */
	public abstract String insert(Map<OPTIONS, Object> options);
	/**
	 * 新增SQL
	 *  
	 * @param options 参数
	 * @param data 数据
	 * @return SQL语句
	 */
	public abstract String insert(Map<OPTIONS, Object> options, Map<String, Object> data);
	
	/**
	 * 更新SQL
	 * 
	 * @param options 参数
	 * @return SQL语句
	 */
	public abstract String update(Map<OPTIONS, Object> options);
	/**
	 * 更新SQL
	 * 
	 * @param options 参数
	 * @param data 数据
	 * @return SQL语句
	 */
	public abstract String update(Map<OPTIONS, Object> options, Map<String, Object> data);
}